home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
pcr
/
pcr4_4.lha
/
DIST
/
threads
/
ThreadsMachDep.s
< prev
next >
Wrap
Text File
|
1991-12-04
|
6KB
|
275 lines
/*
* ThreadsMachDep.s for SPARC processor
*
* Demers, January 25, 1991 4:21:32 pm PST
* Boehm, July 11, 1990 6:17:29 pm PDT
*/
#include <sun4/trap.h>
#include "xr/ThreadsInlines.h"
!
!
! XR_Jump3(arg, proc, sp)
!
! call `proc(arg)' with stack pointer initially set to `sp'.
!
!
! XR_Jump5(arg, proc, sp, opc, osp)
!
! call `proc(arg)' with stack pointer initially set to `sp'.
! make frame look (to dbx) like caller was running on (opc, osp) context.
!
.seg "text"
.proc 16
.globl _XR_Jump3
_XR_Jump3:
t ST_FLUSH_WINDOWS
mov %sp,%fp ! frame pointer
add %o2,-96,%sp ! new sp
clr %i7
call %o1
nop
t ST_DIV0
!
!
.seg "text"
.proc 16
.globl _XR_Jump5
_XR_Jump5:
t ST_FLUSH_WINDOWS
mov %o4,%fp ! frame pointer
add %o2,-96,%sp ! new sp
mov %o3,%i7 ! return pointer
call %o1
nop
t ST_DIV0
!
! old = XR_TestAndSet (ax)
! int * ax;
!
! atomically test *ax and set it to non-0.
!
! n.b. presupposes 0 == FALSE, non-0 == TRUE
!
.seg "text"
.proc 16
.globl _XR_TestAndSet
_XR_TestAndSet:
!
! The followng obvious implementation fails if it has to be restarted (e.g.
! because of a write-protect fault caused by our garbage collector):
!
! ldstub [%o0],%o0
! retl
! nop
!
stb %g0,[%o0+3] ! partially circumvent reputed ldstub bug
ldstub [%o0],%g1
retl
mov %g1,%o0 ! delay slot
!
! replacement for cerror
!
! stores error value in p_errno field (displacement 0) of *XR_currThread
!
.seg "data"
.globl _errno,_XR_currThread
.align 4
! THE FOLLOWING DEFINES MUST AGREE WITH Threads.h
#define T_ERRNO_OFF 0
#define T_ERRNOLOCK_OFF 4
#define T_VPETORESCHEDONMONITOREXIT_OFF 8
#define T_MLNEEDED_OFF 12
!
! _errno is now declared in per-processor state
!
! _errno:
! .word 0
.seg "text"
.proc 16
.globl cerror
cerror:
! _errno := error number from %o0
sethi %hi(_errno),%g1
st %o0,[%g1+%lo(_errno)]
! %g1 := XR_currThread
sethi %hi(_XR_currThread),%g1
ld [%g1+%lo(_XR_currThread)],%g1
! if( %g1 == NIL ) goto out
tst %g1
bz out
nop
! %g1 := %g1->t_errnoLock
ld [%g1+%lo(T_ERRNOLOCK_OFF)],%g1
! if( %g1 != 0 ) goto out
tst %g1
bnz out
! %g1 := XR_currThread
sethi %hi(_XR_currThread),%g1 ! delay slot ok
ld [%g1+%lo(_XR_currThread)],%g1
! %g1->t_errno := error number from %o0
st %o0,[%g1+%lo(T_ERRNO_OFF)]
out:
! return( -1 )
retl
mov -1,%o0 ! delay slot
!
!
! Replacement for _setjmp / _longjmp
!
! Doesn't do Sun's check-for-longjmp-0 hack.
!
! This uses three cells of the jmp_buf:
!
! buf[0] (offset=0): saved pc (exactly as stored by the call instruction)
! buf[1] (offset=4): not used
! buf[2] (offset=8): saved sp (stored here for compatibility with _setjmp)
!
.seg "text"
.proc 16
.globl _XR_setjmp
_XR_setjmp:
st %sp,[%o0+8]
st %o7,[%o0]
retl
clr %o0 ! delay slot
!
!
.seg "text"
.proc 16
.globl _XR_longjmp
_XR_longjmp:
t ST_FLUSH_WINDOWS
sub %sp,64,%sp ! leave space for another copy of regs in case
! preempted while fp and sp inconsistent below.
! (this is why C library versions of _setjmp/
! _longjmp can't be used)
ld [%o0+8],%fp
sub %fp,64,%sp
ld [%o0],%i7 ! return ptr
ret
restore %o1,0,%o0 ! delay slot
!
!
! Flush SPARC register windows
!
!
.seg "text"
.proc 16
.globl _XR_FlushWindows
_XR_FlushWindows:
t ST_FLUSH_WINDOWS
retl
nop
!
!
! Accelerators for monitor entry and exit
!
!
#if (XR_MONITOR_ENTRY || XR_MONITOR_EXIT)
! THE FOLLOWING MUST BE CONSISTENT WITH typedef XR_ML in Threads.h
# define ML_LOCK_OFF 0
# define ML_WQTAIL_OFF 4
# define ML_HOLDER_OFF 8
#endif
#if XR_MONITOR_ENTRY
!
! XR_MonitorEntry(ml)
!
.seg "text"
.proc 16
.globl _XR_MonitorEntry
.globl _XR_MonitorEntryOutOfLine
.globl _XR_currThread
.align 4
_XR_MonitorEntry:
! g1 := TestAndSet(ml->ml_wq.wq_gsl)
! stb %g0,[%o0+3] ! circumvent reputed ldstub bug
ldstub [%o0+ML_LOCK_OFF],%g1
! o1 := ml->ml_holder
ld [%o0+ML_HOLDER_OFF],%o1
! o2 := XR_currThread
sethi %hi(_XR_currThread),%o2
ld [%o2+%lo(_XR_currThread)],%o2
! if( g1 != 0 ) goto MonEntryCall;
tst %g1
bnz MonEntryCall
! if( ml->ml_holder == NIL )
! { ml->ml_holder = XR_currThread; goto EasyMonEntry; }
tst %o1 ! delay slot ok
bz,a EasyMonEntry
st %o2,[%o0+ML_HOLDER_OFF]
MonEntryCallWithLock:
! Unset(ml->ml_wq.wq_gsl);
st %g0,[%o0+ML_LOCK_OFF]
MonEntryCall:
! transfer to XR_MonitorEntryOutOfLine
sethi %hi(_XR_MonitorEntryOutOfLine),%g1
jmpl %g1+%lo(_XR_MonitorEntryOutOfLine),%g0
nop
EasyMonEntry:
! return; Unset(ml->ml_wq.wq_gsl)
retl
st %g0,[%o0+ML_LOCK_OFF] ! delay slot
#endif
#if XR_MONITOR_EXIT
!
! XR_MonitorExit(ml)
!
.seg "text"
.proc 16
.globl _XR_MonitorExit
.globl _XR_MonitorExitOutOfLine
.align 4
_XR_MonitorExit:
! g1 := TestAndSet(ml->ml_wq.wq_gsl)
! stb %g0,[%o0+3] ! circumvent reputed ldstub bug
ldstub [%o0+ML_LOCK_OFF],%g1
! o1 := ml->ml_wq.wq_tail
ld [%o0+ML_WQTAIL_OFF],%o1
! o2 := XR_currThread
sethi %hi(_XR_currThread),%o2
ld [%o2+%lo(_XR_currThread)],%o2
! if( g1 != 0 ) goto MonExitCall;
tst %g1
bnz MonExitCall
! o2 := XR_currThread->t_vpeToReschedOnMonitorExit;
ld [%o2+T_VPETORESCHEDONMONITOREXIT_OFF],%o2 ! delay slot OK
! if( ml->ml_wq.wq_tail != NIL ) { goto MonExitCallWithLock; }
tst %o1 ! delay slot OK
bnz MonExitCallWithLock
! if( XR_currThread->t_vpeToReschedOnMonitorExit == NIL )
! { ml->ml_holder := NIL; goto EasyMonExit; }
tst %o2 ! delay slot OK
bz,a EasyMonExit
st %g0,[%o0+ML_HOLDER_OFF] ! annulled delay slot
MonExitCallWithLock:
! release lock
st %g0,[%o0+ML_LOCK_OFF]
MonExitCall:
! transfer to XR_MonitorExitOutOfLine
sethi %hi(_XR_MonitorExitOutOfLine),%g1
jmpl %g1+%lo(_XR_MonitorExitOutOfLine),%g0
nop
EasyMonExit:
! Unset(ml->ml_wq.wq_gsl); return
retl
st %g0,[%o0+ML_LOCK_OFF] ! delay slot
#endif